package com.flyemu.share.api;

import cn.hutool.cache.CacheUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.flyemu.share.dto.VoucherDto;
import com.flyemu.share.entity.RelationAccount;
import com.flyemu.share.exception.ServiceException;
import com.flyemu.share.service.RelationAccountService;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.Set;


@Service
@Slf4j
@RequiredArgsConstructor
public final class Fenxi {
    @Resource
    private ObjectMapper objectMapper;

    private final RelationAccountService relationAccountService;


    /**
     * 加载帐套信息
     * @param relationAccount
     * @param accountSetsId
     * @return
     */
    public JSONArray loadAccountSets(RelationAccount relationAccount, Long accountSetsId) {
        JSONObject res = this.executeJson(0,  relationAccount.getUrl() + "/account-sets",  accountSetsId, relationAccount);
        log.info("帐套信息", res);
        return res.getJSONArray("data");
    }

    /**
     * 加载科目
     * @param relationAccount
     * @param accountSetsId
     * @return
     */
    public JSONArray loadSubject(RelationAccount relationAccount,  Long accountSetsId) {
        JSONObject res = this.executeJson(0, relationAccount.getUrl() + "/subject/voucher/select", accountSetsId, relationAccount);
        log.info("科目", res);
        return res.getJSONArray("data");
    }

    /**
     * 加载账号分类
     * @param relationAccount
     * @param accountSetsId
     * @param categoryIdSet
     * @return
     */
    public JSONObject loadAccountingCategory(RelationAccount relationAccount, Long accountSetsId, Set<Long> categoryIdSet) {
        HttpRequest post = HttpUtil.createPost(relationAccount.getUrl() + "/accounting-category/byid");
        post.body(JSON.toJSONString(categoryIdSet), "application/json");
        return execute(post, 0,  accountSetsId, relationAccount);
    }

    /**
     * 加载凭证
     * @param relationAccount
     * @param accountSetsId
     * @param voucherId
     * @return
     */
    public JSONObject loadVoucher(RelationAccount relationAccount,  Long accountSetsId, Long voucherId) {
        JSONObject res = this.executeJson(0,  relationAccount.getUrl() + "/voucher" + "/" + voucherId,  accountSetsId, relationAccount);
        log.info("凭证详情", res);
        return res.getJSONObject("data");
    }

    /**
     * 加载凭证字
     * @param relationAccount
     * @param accountSetsId
     * @return
     */
    public JSONArray loadVoucherWord(RelationAccount relationAccount,  Long accountSetsId) {
        JSONObject res = this.executeJson(0, relationAccount.getUrl() + "/voucher-word",  accountSetsId, relationAccount);
        log.info("加载凭证字", res);
        return res.getJSONArray("data");
    }

    /**
     * 加载凭证号
     * @param relationAccount
     * @param accountSetsId
     * @param word
     * @param currentAccountDate
     * @return
     * @throws UnsupportedEncodingException
     */
    public Integer loadWordCode(RelationAccount relationAccount,  Long accountSetsId, String word, LocalDate currentAccountDate) throws UnsupportedEncodingException {
        JSONObject res = this.executeJson(0, relationAccount.getUrl() + "/voucher/code" + "?word=" + URLEncoder.encode(word, "UTF-8") + "&currentAccountDate=" + currentAccountDate,  accountSetsId, relationAccount);
        log.info("凭证号", res);
        return res.getInteger("data");
    }


    /**
     * 新建凭证
     * @param relationAccount
     * @param accountSetsId
     * @param dto
     * @return
     * @throws JsonProcessingException
     */
    public JSONObject createVoucher(RelationAccount relationAccount, Long accountSetsId, VoucherDto dto) throws JsonProcessingException {
        HttpRequest post = HttpUtil.createPost(relationAccount.getUrl() + "/voucher");
        post.body(objectMapper.writeValueAsString(dto), "application/json");
        return execute(post, 0, accountSetsId, relationAccount).getJSONObject("data");
    }


    /**
     * 更新凭证
     * @param relationAccount
     * @param accountSetsId
     * @param dto
     * @return
     * @throws JsonProcessingException
     */
    public JSONObject upVoucher(RelationAccount relationAccount,  Long accountSetsId, VoucherDto dto) throws JsonProcessingException {
        HttpRequest post = HttpRequest.put(relationAccount.getUrl() + "/voucher");
        post.body(objectMapper.writeValueAsString(dto), "application/json");
        return execute(post, 0, accountSetsId, relationAccount).getJSONObject("data");
    }


    private JSONObject executeJson(int retry,  String url, Long accountSetsId, RelationAccount relationAccount) {
        HttpRequest request = HttpUtil.createGet(url);
        request.header("cookie", relationAccount.getCookie());
        if (accountSetsId != null) {
            request.header("accountSetId", accountSetsId.toString());
        }
        HttpResponse response = request.execute();
        if (response.isOk()) {
            log.debug("workflowFormsSchemasProcessCodes：{}", response.bodyBytes());
            return JSON.parseObject(response.bodyBytes());
        } else if (401 == response.getStatus() && retry < 3) {
            relationAccount = relationAccountService.upCookie(relationAccount.getMerchantId(), relationAccount.getOrganizationId());
            return executeJson(retry + 1,  url, accountSetsId, relationAccount);
        } else {
            throw new ServiceException("workflowFormsSchemasProcessCodes HttpCode：" + response.getStatus());
        }
    }

    private JSONObject execute(HttpRequest post, int retry, Long accountSetsId, RelationAccount relationAccount) {
        post.header("cookie", relationAccount.getCookie());
        post.header("accountSetId", accountSetsId.toString());
        HttpResponse response = post.execute();
        if (response.isOk()) {
            JSONObject jsonObject = JSON.parseObject(response.body());
            if (0 == jsonObject.getIntValue("error_code")) {
                return jsonObject;
            } else if (401 == response.getStatus() && retry < 3) {
                relationAccount = relationAccountService.upCookie(relationAccount.getMerchantId(), relationAccount.getOrganizationId());
                return execute(post, retry + 1, accountSetsId, relationAccount);
            }
            throw new HttpException(jsonObject.getString("errmsg"));
        }
        throw new ServiceException("财务系统提示：" + JSON.parseObject(response.body()).getString("msg"));
//        throw new HttpException("{}请求失败", post.getUrl());
    }


}
